package com.prodog.gamemodule.fight.util;

import cn.hutool.core.util.RandomUtil;
import com.prodog.gamemodule.fight.action.entity.FightAction;
import com.prodog.gamemodule.fight.fightobj.entity.FightObj;
import com.prodog.gamemodule.fight.fightobj.entity.FightSkill;
import com.prodog.gamemodule.fight.session.FightSession;

import java.util.*;
import java.util.stream.Collectors;

public class FightUtil {
    public static String fightInfo(FightSession session) {
        StringBuilder sb = new StringBuilder();
        sb.append("                    【红方信息】\n");
        session.getRedObjs().values().forEach(obj -> sb.append(obj.fightHpTpPanel()).append("\n"));
        sb.append("                    【蓝方信息】\n");
        session.getBlueObjs().values().forEach(obj -> sb.append(obj.fightHpTpPanel()).append("\n"));
        return sb.toString().trim();
    }

    public static String fightInfo(FightSession session, String uuid) {
        StringBuilder sb = new StringBuilder();
        FightObj fightObj = session.getObjsByUuid().get(uuid);
        sb.append("                    [我方信息]\n");
        session.getObjsByUuid().values().stream().filter(obj -> obj.getFlag() == fightObj.getFlag()).forEach(obj -> sb.append(obj.fightHpTpPanel()).append("\n"));
        sb.append("\n");
        sb.append("                    [敌方信息]\n");
        session.getObjsByUuid().values().stream().filter(obj -> obj.getFlag() != fightObj.getFlag()).forEach(obj -> sb.append(obj.fightHpTpPanel()).append("\n"));
        return sb.substring(0, sb.length() - 1);
    }

    public static List<FightObj> getEnemys(FightSession session, FightObj fightObj) {
        Integer enemyFlag = fightObj.getFlag() == 0 ? 1 : 0;
        return session.getObjsByUuid().values().stream()
                .filter(enemy -> enemy.getFlag() == enemyFlag)
                .collect(Collectors.toList());
    }

    public static List<FightObj> getAliveEnemys(FightSession session, FightObj fightObj) {
        return getEnemys(session, fightObj).stream()
                .filter(enemy -> enemy.getState() != 2)
                .collect(Collectors.toList());
    }

    public static List<FightObj> getTeams(FightSession session, FightObj fightObj) {
        return session.getObjsByUuid().values().stream()
                .filter(enemy -> enemy.getFlag() == fightObj.getFlag())
                .collect(Collectors.toList());
    }

    public static List<FightObj> getAliveTeams(FightSession session, FightObj fightObj) {
        return getTeams(session, fightObj).stream()
                .filter(enemy -> enemy.getState() != 2)
                .collect(Collectors.toList());
    }

    public static List<FightSkill> getEnableSkills(FightObj fightObj) {
        Collection<FightSkill> skills = fightObj.getSkills().values();
        List<FightSkill> enableSkills = skills.stream()
                .filter(skill -> !fightObj.getCoolTimeMap()
                        .containsKey(FightSession.coolTimePrefixMap.get(FightAction.ACTION_TYPE_ATTACK) + skill.getId()) && skill.getConsumeMp() <= fightObj.getFightProp().getCurMp() && skill.getSkillType() != 3)
                .collect(Collectors.toList());
        return enableSkills;
    }

    public static boolean hasSkill(FightObj fightObj, String skillId) {
        if (skillId == null) {
            return false;
        }
        return fightObj.getSkills().values().stream().anyMatch(skill -> skill.getId().equals(skillId));
    }

    public static boolean isSkillCooling(FightObj fightObj, String skillId) {
        return fightObj.getCoolTimeMap().containsKey("SKILL:" + skillId);
    }

    public static boolean isItemCooling(FightObj fightObj, String itemId) {
        return fightObj.getCoolTimeMap().containsKey("ITEM:" + itemId);
    }

    public static int getSkillCoolTime(FightObj fightObj, String skillId) {
        Integer coolTime = fightObj.getCoolTimeMap().get("SKILL:" + skillId);
        return coolTime == null ? 0 : coolTime;
    }

    public static int getItemCoolTime(FightObj fightObj, String itemId) {
        Integer coolTime = fightObj.getCoolTimeMap().get("ITEM:" + itemId);
        return coolTime == null ? 0 : coolTime;
    }

    public static boolean isHpEnough(FightObj fightObj, String skillId) {
        return fightObj.getSkills().get(skillId).getConsumeHp() <= fightObj.getFightProp().getCurHp();
    }

    public static boolean isMpEnough(FightObj fightObj, String skillId) {
        return fightObj.getSkills().get(skillId).getConsumeMp() <= fightObj.getFightProp().getCurMp();
    }

    public static boolean isEnemyDead(FightSession session, FightObj obj, int index) {
        List<FightObj> enemys = getEnemys(session, obj);
        return enemys.get(index).getState() == 2;
    }

    public static boolean isTeamDead(FightSession session, FightObj obj, int index) {
        List<FightObj> teams = getTeams(session, obj);
        return teams.get(index).getState() == 2;
    }

    public static List<FightObj> orderBySpped(Map<Object, FightObj> objsByUuid) {
        return orderBySpped(objsByUuid.values());
    }

    private static List<FightObj> orderBySpped(Collection<FightObj> objs) {
        List<FightObj> collect = objs.stream().filter(obj -> obj.getState() != 2 && !obj.isOver())
                .sorted(Comparator.comparing(obj -> obj.getFightProp().getSpeed()))
                .collect(Collectors.toList());
        Collections.reverse(collect);
        return collect;
    }

    public static List<FightObj> getBeActedObjs(FightSession session, FightObj obj, FightSkill skill) {
        //获取作用的对象列表
        List<FightObj> objs = skill.isAffectTeam() ? getTeams(session, obj) : getEnemys(session, obj);
        if (skill.isIgnoreDead()) {
            if (objs.size() <= skill.getTargetNums()) {
                return objs;
            }
            int size = objs.size();
            int targetNums = skill.getTargetNums();
            if (targetNums == 0) {
                return new ArrayList<>();
            }
            int startIndex = obj.getAction().getIndex();
            int endIndex = startIndex + targetNums;
            if (endIndex >= size) {
                int big = endIndex - size;
                endIndex = size - 1;
                startIndex -= big;
                return objs.subList(startIndex, endIndex);
            }
        } else {
            List<FightObj> aliveObjs = skill.isAffectTeam() ? getAliveTeams(session, obj) : getAliveEnemys(session, obj);
            if (aliveObjs.size() <= skill.getTargetNums()) {
                return aliveObjs;
            }
            FightObj beActedObj = objs.get(obj.getAction().getIndex());
            int size = aliveObjs.size();
            int targetNums = skill.getTargetNums();
            int startIndex = beActedObj.getState() != 2 ? aliveObjs.indexOf(beActedObj) : RandomUtil.randomInt(0, aliveObjs.size());
            int endIndex = startIndex + targetNums;
            if (endIndex >= size) {
                int big = endIndex - size;
                endIndex = size - 1;
                startIndex -= big;
            }
            if (startIndex == endIndex) {
                return Arrays.asList(aliveObjs.get(startIndex));
            }
            return aliveObjs.subList(startIndex, endIndex);
        }
        return new ArrayList<>();
    }

    public static int getVictory(FightSession session) {
        List<FightObj> aliveReds = getAliveTeams(session, new FightObj() {{
            setFlag(0);
        }});
        List<FightObj> aliveBlues = getAliveTeams(session, new FightObj() {{
            setFlag(1);
        }});
        if (aliveReds.size() == 0) {
            return 1;
        } else if (aliveBlues.size() == 0) {
            return 0;
        }
        return -1;
    }

    public static FightSkill getNormalAttack(FightObj obj) {
        return obj.getSkills().values().stream().filter(skill -> skill.isNormal()).findAny().get();
    }
}
